package com.project.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.commons.lang3.StringUtils;

/**
 * 利用java反射(reflect)自动赋值实体类的值
 * @author chen.liangzhen
 * @time 2017年3月6日 下午3:52:37
 */
public class AutoSetVoValue {
	/**
	 * 利用java反射自动赋值实体类的值
	 * @author chen.liangzhen
	 * @time 2017年3月9日 下午3:07:05
	 * @version
	 * @param model
	 * @param fields
	 * @param values
	 * @return
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws InstantiationException
	 */
	public static <T> T autoSetValue(Class<T> model, String[] fields, Object[] values)
			throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException,
			InvocationTargetException, InstantiationException {

		if (null == model) {
			System.out.println("model为空！");
			return null;
		}

		if (null == fields || fields.length <= 0) {
			System.out.println("fields为空！");
			return null;
		}

		if (null == values || values.length == 0) {
			System.out.println("values为空！");
			return null;
		}

		T bean = model.newInstance();

		// 获取实体类的所有属性，返回Field数组
		Field[] field = model.getDeclaredFields();

		for (int i = 0; i < field.length; i++) {
			// 获取属性的名字
			String name = field[i].getName();
			if (StringUtils.isBlank(name)) {
				continue;
			}

			// 获取属性类型
			// String type = field[i].getGenericType().toString();
			Class<?> types = field[i].getType();

			// 关键。。。可访问私有变量
			field[i].setAccessible(true);

			// 将属性的首字母大写
			name = name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());

			// 获取set方法
			Method method = model.getDeclaredMethod("set" + name, types);

			for (int j = 0; j < fields.length; j++) {
				if (name.toLowerCase().equals(fields[j].toLowerCase())) {
					// 调用setter方法设置属性值
					method.invoke(bean, values[j]);
					break;
				}
			}
		}
		return bean;
	}
	
	/**
	 * 利用java反射自动赋值实体类的值的插件
	 * @author chen.liangzhen
	 * @time 2017年3月15日 上午10:43:22
	 * @version
	 * @param model
	 * @param fields
	 * @param values
	 * @return
	 * @throws Exception
	 */
	public static <E> E autoSetValuePlugn(Class<? extends E> model, String[] fields, Object[] values)
			throws Exception{
		
		if (null == model) {
			System.out.println("model为空！");
			return null;
		}

		if (null == fields || fields.length <= 0) {
			System.out.println("fields为空！");
			return null;
		}

		if (null == values || values.length == 0) {
			System.out.println("values为空！");
			return null;
		}
		
		E o = (E)model.newInstance();
		Field[] field = model.getDeclaredFields();
		for(Field f : field){
			// 获取属性的名字
			String name = f.getName();
			if (StringUtils.isBlank(name)) {
				continue;
			}
			
			for (int j = 0; j < fields.length; j++) {
				if(fields[j].equalsIgnoreCase(name)){
					PropertyDescriptor pd = new PropertyDescriptor(name, model);
					Method m = pd.getWriteMethod();
					m.invoke(o, values[j]);
				}
			}
		}
		return o;
	}
}
